﻿using System;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Threading;
using System.Windows.Forms;

namespace NotWindowsStoreClient.Lib
{
    public class WindowsStoreClientService
    {
        private Thread _thread;
        private bool _run;
        private string _storageSource;
        private string _storageStage;
        private string _installBatFileName;

        public void Start()
        {
            _storageSource = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
            _storageStage = Path.Combine(_storageSource, @"stage");
            _installBatFileName = Path.Combine(_storageStage, "Add-AppxDevPackage.bat");
            Directory.CreateDirectory(_storageSource);
            Directory.CreateDirectory(_storageStage);

            CreateInstallBat();

            _run = true;
            _thread = new Thread(MonitorLoop);
            _thread.Start();
        }

        private void CreateInstallBat()
        {
            using (var installBatStream = GetType().Assembly.GetManifestResourceStream("NotWindowsStoreClient.Lib.Add-AppxDevPackage.bat"))
            using (var outStream = File.Open(_installBatFileName, FileMode.Create))
            {
                if (installBatStream == null)
                {
                    throw new Exception("Could not open install resource");
                }

                int read;
                byte[] buffer = new byte[1024];
                while ((read = installBatStream.Read(buffer, 0, buffer.Length)) > 0)
                {
                    outStream.Write(buffer, 0, read);
                }
            }
        }

        public void Stop()
        {
            _run = false;
        }

        private void MonitorLoop()
        {
            while (_run)
            {
                Thread.Sleep(1000);

                try
                {
                    foreach (var fileName in Directory.GetFiles(_storageSource, "*.nwsapp"))
                    {
                        if (fileName.EndsWith("ready.nwsapp"))
                        {
                            Thread.Sleep(100);
                            File.Delete(fileName);
                            string originalWithoutExtension = fileName.Substring(0, fileName.Length - 13);
                            string oldFile = originalWithoutExtension + ".nwsapp";
                            var targetFileName = Path.Combine(_storageStage, Path.GetFileName(originalWithoutExtension));
                            File.Move(oldFile, targetFileName);
                        }
                    }

                    var stagingExtensions = Directory.GetFiles(_storageStage)
                        .Select(s => (Path.GetExtension(s) ?? "").ToLowerInvariant())
                        .ToList();
                    if (stagingExtensions.Any(s => s == ".appx") && stagingExtensions.Any(s => s == ".cer"))
                    {
                        CallInstallBat();
                        foreach (
                            var fileNameToDelete in
                                Directory.GetFiles(_storageStage).Where(s => s.EndsWith(".appx") || s.EndsWith(".cer")))
                        {
                            File.Delete(fileNameToDelete);
                        }
                    }
                }
                catch (Exception ex)
                {
                    MessageBox.Show("Failed to install: " + ex);
                }
            }
        }

        private void CallInstallBat()
        {
            var proc = new Process
            {
                StartInfo =
                {
                    FileName = _installBatFileName,
                    Verb = "runas"
                }
            };
            proc.Start();
            proc.WaitForExit();
        }
    }
}
